// AnsiTerminalView.h : interface of the CAnsiTerminalView class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_ANSITERMINALVIEW_H__A4AF8BD4_2FB9_45FB_B8DC_E9C0064FCC36__INCLUDED_)
#define AFX_ANSITERMINALVIEW_H__A4AF8BD4_2FB9_45FB_B8DC_E9C0064FCC36__INCLUDED_

#include "SessionOptions.h"
#include "IAnsiScreenEvents.h"
#include "GlobalConsts.h"
#include "SelectionHandler.h"

#include "AnsiScreen.h"


#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CAnsiTerminalDoc;

class CAnsiTerminalView : public CScrollView
{
private:
	class CAppIdleListener : public IAppIdleListener
	{
	private:
		CAnsiTerminalView* m_pOuter;
	public:
		virtual void OnAppIdle()
		{
 			if(m_pOuter->m_screenEvents.m_screenChanged)
 				m_pOuter->OnTimer(ID_TIMER_UPDATEWINDOW);
			
			if(m_pOuter->m_screenEvents.m_caretMoved)
				m_pOuter->OnTimer(ID_TIMER_UPDATECARETPOS);

			m_pOuter->ShowCaret();
		}
		CAppIdleListener(CAnsiTerminalView* pOuter)
		{
			m_pOuter = pOuter;
		}
	} m_appIdleListener;
	friend class CAppIdleListener;
	
	class CAnsiScreenEvents : public IAnsiScreenEvents
	{
	private:
		CAnsiTerminalView* m_pOuter;
		CAnsiScreen *m_pScreen;
	public:
		CRect m_changedRegion;
		BOOL m_screenChanged;
		BOOL m_caretMoved;
	public:
		void OnChange(int x1, int y1, int x2, int y2)
		{
			m_pOuter->HideCaret();
			if(!m_screenChanged)
			{
				m_changedRegion.SetRect(x1, y1, x2, y2);
				m_screenChanged = TRUE;
			}
			else
			{
				if(x1 < m_changedRegion.left)
				{
					m_changedRegion.left = x1;
				}
				if(x2 > m_changedRegion.right)
				{
					m_changedRegion.right = x2;
				}
				if(y1 < m_changedRegion.top)
				{
					m_changedRegion.top = y1;
				}
				if(y2 > m_changedRegion.bottom)
				{
					m_changedRegion.bottom = y2;
				}
			}
			m_pOuter->SetTimer(ID_TIMER_UPDATEWINDOW, 10, 0);
		}
		void OnCaretMove()
		{
			m_caretMoved = TRUE;
			m_pOuter->SetTimer(ID_TIMER_UPDATECARETPOS, 11, 0);
		}
		void OnScreenUp(int lineCount)
		{
 			if(m_screenChanged)
 				m_pOuter->OnTimer(ID_TIMER_UPDATEWINDOW);
			m_pOuter->m_scrollCount += lineCount;
			m_pOuter->SetTimer(ID_TIMER_UPDATEWINDOW, 10, 0);

		}
		void SetScreen(CAnsiScreen *pScreen)
		{
			m_pScreen = pScreen;
		}
		void OnSetCursor(HCURSOR hCursor)
		{
			m_pOuter->m_hCursor = hCursor;
			if(hCursor)
			{
				SetCursor(hCursor);
			}
			else
			{
				SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));
			}
		}
		void OnFlushChange()
		{
 			if(m_screenChanged)
 				m_pOuter->OnTimer(ID_TIMER_UPDATEWINDOW);
		}
		CAnsiScreenEvents(CAnsiTerminalView* pOuter)
		{
			m_pOuter = pOuter;
			m_screenChanged = FALSE;
			m_changedRegion.SetRectEmpty();
			m_caretMoved = FALSE;
		}
	} m_screenEvents;
	friend class CAnsiScreenEvents;
	BOOL m_screenChanged;
	CRect m_changedRegion;

protected: // create from serialization only
	CAnsiTerminalView();
	DECLARE_DYNCREATE(CAnsiTerminalView)

// Attributes
public:
	CAnsiTerminalDoc* GetDocument();
	

protected:
	CFont m_font;
	CSize m_cellSize;
	BOOL m_initialUpdated;
	BOOL m_bBlinking;
	HCURSOR m_hCursor;
	int m_scrollCount;
// 	BOOL m_screenChanged;

// 	CPoint m_ptDown;
	CPoint m_ptDownCell;
// 	CPoint m_ptMove;
	CPoint m_ptMoveCell;
	BOOL m_bDowned;

	CSelectionHandler m_selectionHandler;
	
	void UpdateScrollBar();
	void UpdateCanvasSize(int cx = 0, int cy = 0, BOOL bUpdateFont = FALSE);
	void PositionCaret();
	void UpdateCanvasMode(BOOL bUpdateFont = FALSE);
	void UpdateRegion(CRect rcRegion, BOOL bUpdateWindow = TRUE);
	CPoint DevicePointToCellPoint(const CPoint& point);

	BOOL m_bShowCaret;
	void HideCaret();
	void ShowCaret();

	void HideBlinkTexts();

	UINT m_blinkCount;
	void TryHideCursor();
	void TryShowCursor();

// Operations
public:
	void Refresh();

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAnsiTerminalView)
	public:
	virtual void OnDraw(CDC* pDC);  // overridden to draw this view
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	virtual void OnInitialUpdate();
	protected:
	virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
	virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~CAnsiTerminalView();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
	//{{AFX_MSG(CAnsiTerminalView)
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnTimer(UINT nIDEvent);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
	afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint point);
	afx_msg void OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags);
	//}}AFX_MSG
	afx_msg LRESULT OnMoveCaret(WPARAM, LPARAM);
	DECLARE_MESSAGE_MAP()
};

#ifndef _DEBUG  // debug version in AnsiTerminalView.cpp
inline CAnsiTerminalDoc* CAnsiTerminalView::GetDocument()
   { return (CAnsiTerminalDoc*)m_pDocument; }
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_ANSITERMINALVIEW_H__A4AF8BD4_2FB9_45FB_B8DC_E9C0064FCC36__INCLUDED_)
